package com.lwx.chapter2;


import org.omg.CORBA.Object;

public class Array<E> {
    private E[] data;
    /**
     * 既代表数组中的数据个数，又代表数组中第一个空位置的下标
     */
    private int size;

    public Array(int capacity){
        //创建泛型数组，->需要泛型的Class，->通过下面这种方法可以得到泛型的的Class
        data = (E[])new Object[capacity];

        size = 0;
    }

    public Array(E[] arr){
        data = (E[]) new Object[arr.length];
        for (int i = 0; i < arr.length; i++) {
            data[i] = arr[i];
        }
        size = arr.length;
    }

    /**
     * 当没有给定数组容量时，默认开辟10个空间
     */
    public Array(){
        this(10);
    }

    public int getSize(){
        return size;
    }

    public int getCapacity(){
        return data.length;
    }

    public boolean isEmpty(){
        return data.length == 0;
    }

    /**
     * 没有指定位置插入,插入数组的最后
     */
    public void addLast(E e){
        add(size,e);
    }

    public void addFirst(E e){
        add(0,e);
    }

    /**
     * 在指定的位置插入插入元素
     * @param index 数组下标
     * @param e
     */
    public void add(int index, E e){
        if(data.length == size){
           resize(data.length *2);
        }
        //插入的时候需要紧凑着插入,index==size为插入数组的最后一位
        if(index <0 || index >size){
            throw new IllegalArgumentException("Add failed.index<=0||index>size is error");
        }
        for (int i = size-1; i >=index; i--) {
            data[i+1] = data[i];
        }
        data[index] = e;
        size++;
    }


    //查询
    E get(int index){
        if(index <0 || index >size){
            throw new IllegalArgumentException("Get failed.index<=0||index>size is illegal");
        }
        return  data[index];
    }

    //更新
    void set(int index, E e){
        if(index <0 || index >size){
            throw new IllegalArgumentException("Set failed.index<=0||index>size is illegal");
        }
        data[index] = e;
    }

    //包含
    public boolean contains(E e){
        for (int i = 0; i < size; i++) {
            if(data[i].equals(e)){
                return true;
            }
        }
        return false;
    }

    //查找元素e,并返回索引, 查找第一个元素e
    //findAll
    public int fint(E e){
        for (int i = 0; i < size; i++) {
            if(data[i].equals(e)){
                return i;
            }
        }
        return  -1;
    }

    /**
     *
     * @param index 被删除的元素的下标
     * @return  被删除的元素是什么
     */
    public E remove(int index){
        if(index <0 || index >size){
            throw new IllegalArgumentException("Remove failed.index<=0||index>size is illegal");
        }
        E ret = data[index];
        for (int i = index+1; i < size; i++) {
            data[i-1] = data[i];
        }
        //loitering objects 闲逛对象
//        data[size] = null;
        size --;
        if(size == data.length/2){
            //进行删除时，要对数组长度进行检查，进行容量缩减
            resize(data.length/2);
        }
        return ret;
    }

    public E removeFirst(){
        return remove(0);
    }

    public E removeLast(){
        return remove(size - 1);
    }

    /**
     * 从数组中删除e,只删除一个元素e,removeAll
     * @param e
     */
    public void removeElement(E e){
        int index = fint(e);
        if(index != -1){
            remove(index);
        }
    }

    public void swap(int i, int j){
        if(i < 0|| i >= size||j < 0|| j >= size){
            throw new IllegalArgumentException("Swap failed.Illegal index");
        }
        E t = data[i];
        data[i] = data[j];
        data[j] = t;
    }
    @Override
    public String toString() {
       StringBuilder res = new StringBuilder();
       res.append(String.format("Array size is %d, capacity is %d.\n", size, data.length));
       res.append("[");
        for (int i = 0; i < size; i++) {
            res.append(data[i]);
            if(i!= size-1){
                res.append(",");
            }
        }
        res.append("]");
        return res.toString();
    }

    private void resize(int newCapacity){
        E[] newData = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newData[i] = data[i];
        }
        data = newData;
    }
}
